#ifndef __BSTREE__H__
#define __BSTREE__H__

#include <iostream>
#include <string>
#include "node_manager.h"
#include "register_pack.h"
#include "node.h"
#include "leaf_node.h"
#include "level_node.h"
#include "bsIterator.h"
#include "tree_pack.h"

namespace bstree{

class BSTree{
	protected:
		static const unsigned long OFFSET_ROOT = 0;
	protected:
		NodeManager manager;
		Node* root;
		/* para acelerar las cosas la raiz siempre esta en memoria 
			TODO -> recordar todo el camino de busqueda*/

	public:
		BSTree(unsigned int nodeSize,const RegisterFactory& factory,const RegisterFactory& factoryNivel,const std::string& nodesFilename);
		~BSTree();

		bool insert(const Register& reg);
		bool remove(const Register& reg);
		bool search(Register& reg);
		bool replace(const Register& newReg,const Register& oldReg);
		
		BSIterator* getIterator(const Register& reg);
		
		BSIterator* getFirst();
		BSIterator* getLast();
	private:
		bool nodeInsert(unsigned int nodeOffset,LevelNode* root,const Register& reg);
		void handleLevelOverflow(LevelNode* levelnode,LevelNode* root);
		void handleLeafOverflow(LeafNode* leafNode,LevelNode* root);
		bool nodeRemove(unsigned int nodeOffset,LevelNode* root,const Register& reg);
		void handleLeafUnderflow(LeafNode* leafNode,LevelNode* root,const Register& reg);
		void handleLevelUnderflow(LevelNode* levelNode,LevelNode* root,const Register& reg);
		bool nodeReplace(unsigned int nodeOffset,LevelNode* root,const Register& newReg,const Register& oldReg);
		friend std::ostream& operator <<(std::ostream& out,BSTree& tree);
		/* Por si se usa polimorfismo desde Tree */
		std::ostream& toOstream(std::ostream& out);
};

}

#endif /* __BPPTREE__H__ */
